import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.util.*;

class Exercise6  extends MouseAdapter implements ActionListener,ChangeListener,KeyListener
{
	private int id[][];
	private int result[][];
	private int difficulty;
	private Random random;
	
	private JFrame frame;
	private JTextField text[][];//方格
	private Font font;
	private JMenuBar menu;//菜单栏
	private JMenu game;//游戏按钮->
	private JMenu info;//信息按钮->
	private JPopupMenu gamePopupMenu;//游戏按钮菜单
	private JPopupMenu infoPopupMenu;//信息按钮菜单
	
	private JMenuItem start;//新建游戏
	private JMenuItem exit;//退出
	private JMenuItem hint;//提示
	private JSeparator separator;

	private JMenuItem set;//游戏设定。->
	private JSlider slider;//游戏难度的滚动条
	private JDialog setDialog;//游戏难度设定对话框。
	private JLabel setLabel;
	private JButton setButton;
	
	private JMenuItem check;//检查是否正确->
	private JDialog checkDialog;//检查是否正确的弹出对话框。
	private JLabel checkLabel;
	private JButton checkButton;
	
	private JMenuItem about;//关于－>
	private JDialog aboutDialog;//about对话框。
	private JTextArea aboutText;
	private JButton aboutButton;
	
	public static void main(String args[])
	{
		Exercise6 that = new Exercise6();
		that.go();
	}
	
	public void go()
	{
		int i,j;
		id = new int[9][9];
		result = new int[9][9];
		font = new Font("DialogInput",font.BOLD,40);
		random = new Random();
		
		frame = new JFrame("SUDOKU");
		text = new JTextField[9][9];
		menu = new JMenuBar();
		game = new JMenu("Game");
		info = new JMenu("Help");
		gamePopupMenu = new JPopupMenu();
		infoPopupMenu = new JPopupMenu();

		start = new JMenuItem("New Game",KeyEvent.VK_N);
		exit = new JMenuItem("Exit",KeyEvent.VK_E);
		hint = new JMenuItem("Hint",KeyEvent.VK_H);
		separator = new JSeparator();
		
		set = new JMenuItem("Set Game",KeyEvent.VK_S);
		slider = new JSlider(1,8,5);
		setDialog = new JDialog(frame,"Set SUDOKU");
		setButton =new JButton("Enter");
		setLabel = new JLabel();
		
		check = new JMenuItem("Check",KeyEvent.VK_C);
		checkButton = new JButton("Enter");
		checkDialog = new JDialog(frame,"Check SUDOKU");
		checkLabel = new JLabel();

		about = new JMenuItem("About",KeyEvent.VK_A);
		aboutButton = new JButton("Enter");
		aboutDialog = new JDialog(frame,"About SUDOKU");
		aboutText = new JTextArea("         SUDOKU\nCopyright 2010-3000\n    Wang Hongwei\n  2008010486\n         CS 84\n    Code In Java\n All rights reserved.");

		frame.getContentPane().add(menu);
		for(i=0;i<9;i++)
			for(j=0;j<9;j++)
			{
				text[i][j] = new JTextField(1);
				frame.getContentPane().add(text[i][j]);
			}
			
		menu.add(game);
		menu.add(info);
		game.add(gamePopupMenu);
		info.add(infoPopupMenu);
		gamePopupMenu.add(start);
		gamePopupMenu.add(set);
		gamePopupMenu.add(check);
		gamePopupMenu.add(separator);
		gamePopupMenu.add(exit);
		infoPopupMenu.add(hint);
		infoPopupMenu.add(about);

		setDialog.add(setButton);
		setDialog.add(slider);
		setDialog.add(setLabel);
		
		checkDialog.add(checkButton);
		checkDialog.add(checkLabel);

		aboutDialog.add(aboutButton);
		aboutDialog.add(aboutText);
		
		start.addActionListener(this);
		set.addActionListener(this);
		exit.addActionListener(this);
		hint.addActionListener(this);
		about.addActionListener(this);
		check.addActionListener(this);

		setButton.addKeyListener(this);
		checkButton.addKeyListener(this);
		aboutButton.addKeyListener(this);
		
		setButton.addMouseListener(this);
		checkButton.addMouseListener(this);
		aboutButton.addMouseListener(this);
		
		menu.addMouseListener(this);
		game.addMouseListener(this);
		info.addMouseListener(this);
		start.addMouseListener(this);
		set.addMouseListener(this);
		exit.addMouseListener(this);
		hint.addMouseListener(this);
		about.addMouseListener(this);
		check.addMouseListener(this);
		slider.addMouseListener(this);
		slider.addChangeListener(this);
		
		start.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,ActionEvent.CTRL_MASK+ActionEvent.SHIFT_MASK));
		set.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,ActionEvent.CTRL_MASK+ActionEvent.SHIFT_MASK));
		exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E,ActionEvent.CTRL_MASK+ActionEvent.SHIFT_MASK));
		about.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A,ActionEvent.CTRL_MASK+ActionEvent.SHIFT_MASK));
		hint.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H,ActionEvent.CTRL_MASK+ActionEvent.SHIFT_MASK));
		check.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,ActionEvent.CTRL_MASK+ActionEvent.SHIFT_MASK));

		setButton.setMnemonic(KeyEvent.VK_ENTER);
		checkButton.setMnemonic(KeyEvent.VK_ENTER);
		aboutButton.setMnemonic(KeyEvent.VK_ENTER);
	
		frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
		frame.setLayout(null);
		frame.setVisible(true);
		frame.setResizable(false);//禁用最大化功能。
		frame.getContentPane().setBackground(Color.blue);
		aboutText.setEditable(false);
		aboutText.setColumns(5);
		aboutText.setMargin(new Insets(50, 90, 0, 70));
		checkLabel.setHorizontalAlignment(JTextField.CENTER);
		checkLabel.setFont(font);
		setLabel.setHorizontalAlignment(JTextField.CENTER);
		frame.setSize(595,630);
		menu.setBounds(0,0,596,35);
		for(i=0;i<9;i++)
			for(j=0;j<9;j++)
			{
				text[i][j].setFont(font);
				text[i][j].setHorizontalAlignment(JTextField.CENTER);	
				text[i][j].setBounds(66*i,35+63*j,66,63);
				if((i==3||i==6)&&!(j==2||j==5))
					text[i-1][j].setBounds(66*(i-1),35+63*j,63,63);
				if(!(i==2||i==5)&&(j==3||j==6))
					text[i][j-1].setBounds(66*i,35+63*(j-1),66,60);
				if((i==3||i==6)&&(j==3||j==6))
					text[i-1][j-1].setBounds(66*(i-1),35+63*(j-1),63,60);
			}

		setDialog.setSize(300,300);
		slider.setBounds(100,150,100,50);
		checkDialog.setSize(300,300);
		checkButton.setBounds(100,200,100,50);
		aboutDialog.setSize(300,300);
		aboutButton.setBounds(100,200,100,50);
		setButton.setBounds(100,200,100,50);
		difficulty = 5;
		startGame();
	}
	public void actionPerformed(ActionEvent e)
	{
		if(e.getSource()==exit)
			System.exit(0);
		if(e.getSource()==start)
			startGame();
		if(e.getSource()==hint)
			hintGame();
		if(e.getSource()==set)
			setGame();
		if(e.getSource()==about)
			aboutGame();
		if(e.getSource()==check)
			checkGame();
	}
	public void keyPressed(KeyEvent e)
	{
		if(e.getKeyCode()==KeyEvent.VK_ENTER)
		{
			if(e.getSource()==setButton)
				setDialog.setVisible(false);
			if(e.getSource()==checkButton)
				checkDialog.setVisible(false);
			if(e.getSource()==aboutButton)
				aboutDialog.setVisible(false);
		}
		if(e.getKeyCode()==KeyEvent.VK_UP||e.getKeyCode()==KeyEvent.VK_DOWN||e.getKeyCode()==KeyEvent.VK_RIGHT||e.getKeyCode()==KeyEvent.VK_LEFT)
		{
			System.out.println(true);
			if(setDialog.isVisible()==false&&checkDialog.isVisible()==false&&aboutDialog.isVisible()==false)
			{
				System.out.println(true);
			}
		}
	}
	public void keyReleased(KeyEvent e){}
	public void keyTyped(KeyEvent e){}
	public void	stateChanged(ChangeEvent e)
	{
		if(e.getSource()==slider)
		{
			difficulty = slider.getValue();
			setLabel.setText("The Level of Difficulty of SUDOKU is "+difficulty);
		}
			
	}
	public void mouseClicked(MouseEvent e)
	{
		int i,j;
		if(e.getComponent()==game)
		{
			infoPopupMenu.setVisible(false);
			if(gamePopupMenu.isVisible()==true)
				gamePopupMenu.setVisible(false);
			else
			{
				gamePopupMenu.show(e.getComponent(),0,35);
				gamePopupMenu.setVisible(true);					
			}
		}
		if(e.getComponent()==info)
		{
			gamePopupMenu.setVisible(false);
			if(infoPopupMenu.isVisible()==true)
				infoPopupMenu.setVisible(false);
			else
			{
				infoPopupMenu.show(e.getComponent(),0,35);
				infoPopupMenu.setVisible(true);					
			}
		}
		if(e.getComponent()==start)
			startGame();
		if(e.getComponent()==set)
			setGame();
		if(e.getComponent()==exit)
			System.exit(0);
		if(e.getComponent()==hint)
			hintGame();
		if(e.getComponent()==about)
			aboutGame();
		if(e.getComponent()==check)
			checkGame();
		if(e.getComponent()==setButton)
			setDialog.setVisible(false);
		if(e.getComponent()==checkButton)
			checkDialog.setVisible(false);
		if(e.getComponent()==aboutButton)
			aboutDialog.setVisible(false);
		if(e.getComponent()==slider)
		{
			difficulty = slider.getValue();
			setLabel.setText("The Level of Difficulty of SUDOKU is "+difficulty);
		}
	}
	public void startGame()
	{
		int i,j;
		id = PartMatrix.getRandomMatrix(difficulty);	
		infoPopupMenu.setVisible(false);
		gamePopupMenu.setVisible(false);
		for(i=0;i<9;i++)
		{
			for(j=0;j<9;j++)
			{
				text[i][j].setText(null);
				text[i][j].setEditable(true);
				text[i][j].setBackground(Color.white);
				if(id[i][j]!=0)
				{
					text[i][j].setText((new Integer(id[i][j])).toString());
					text[i][j].setEditable(false);
					text[i][j].setBackground(Color.cyan);
				}
			}
		}		
	}

	public void hintGame()
	{
		infoPopupMenu.setVisible(false);
		gamePopupMenu.setVisible(false);
		int i,j;
		while(true)
		{
			i=random.nextInt(9);
			j=random.nextInt(9);
			if(text[i][j].getText().trim().length()==0) 
			{
				text[i][j].setText((new Integer(Matrix.get(i,j))).toString());
				text[i][j].setBackground(Color.PINK);
				text[i][j].setEditable(false);
				break;
			}
	next:	{
				for(i=0;i<9;i++)
					for(j=0;j<9;j++)
						if(text[i][j].getText().trim().length()==0)
							break next;
				return;
			}
		}		
	}
	public void setGame()
	{
		setLabel.setText("The Level of Difficulty of SUDOKU is "+difficulty);
		infoPopupMenu.setVisible(false);
		gamePopupMenu.setVisible(false);
		setDialog.setVisible(true);
		setButton.grabFocus();
	}
	public void aboutGame()
	{
		infoPopupMenu.setVisible(false);
		gamePopupMenu.setVisible(false);
		aboutDialog.setVisible(true);
		aboutButton.grabFocus();
	}
	public void checkGame()
	{
		int i,j,t=0;
		for(i=0;i<9;i++)
			for(j=0;j<9;j++)
			if(text[i][j].getText().trim().length()==1)
			{
				if(text[i][j].getText().compareTo("9")<=0&&text[i][j].getText().compareTo("0")>0)
					result[i][j] = 	Integer.parseInt(text[i][j].getText());
			}
			else
				result[i][j]=0;
					
		for(i=0;i<9;i++)
			for(j=0;j<9;j++)
			{
				if(!Matrix.check(result,i,j))
				{
					t++;
					text[i][j].setText(null);
					text[i][j].setText((new Integer(Matrix.get(i,j))).toString());
					text[i][j].setEditable(false);
					text[i][j].setBackground(Color.RED);
				}
			}
		if(t!=0)
			checkLabel.setText("Wrong!");
		else
			checkLabel.setText("Right!");
		infoPopupMenu.setVisible(false);
		gamePopupMenu.setVisible(false);
		checkDialog.setVisible(true);
		checkButton.grabFocus();
	}
}
//JTextfield可以用JTable代替，会达到更好的效果，不过并不清楚是否能够划分成3＊3的小宫
//一旦使用了鼠标操作菜单，快捷键就会失效，并不清楚原因
//并没有实现用键盘上下左右的功能
//hint的效果可以再改进，不过并不清楚方法。
//并不清楚如何用一个键例如H直接调出hint命令。
//游戏开始之后，或者点击某一个菜单之后，会出现在左上角，这个问题没有解决。
//数据处理的结构可以进一步优化。
//由于并没有和他人讨论，并不清楚其他的实现方法。
